package com.itheima.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.api.*;
import com.itheima.autoconfig.template.HuanXinTemplate;
import com.itheima.domain.*;
import com.itheima.dto.RecommendUserDto;
import com.itheima.server.exception.BusinessException;
import com.itheima.server.exception.ErrorResult;
import com.itheima.server.interceptor.UserHolder;
import com.itheima.utils.Constants;
import com.itheima.vo.NearUserVo;
import com.itheima.vo.PageResult;
import com.itheima.vo.TodayBest;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TanhuaService {

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @DubboReference
    private UserLikeApi userLikeApi;

    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Resource
    private MessagesService messagesService;;


    @Resource
    private HuanXinTemplate huanXinTemplate;

    @Resource
    private RedisTemplate<String,String> redisTemplate;

    @Value("${tanhua.default.recommend.users}")
    private String recommendUsers;

    /**
     * 查询今日佳人
     * @return
     */
    public TodayBest todayBest() {
        Long userId = UserHolder.getUserId();
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(userId);
        if(recommendUser == null) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(1L);
            recommendUser.setScore(99d);
        }
        UserInfo userInfo = userInfoApi.getById(recommendUser.getUserId());
        return TodayBest.init(userInfo,recommendUser);
    }

    /**
     * 推荐朋友
     * @param
     * @return
     */
    public PageResult recommendation(RecommendUserDto dto) {
        Long toUserId = UserHolder.getUserId();
        //拿着当前用户id去查推荐朋友表,这里要分页查询
        PageResult recommendation = recommendUserApi.recommendation(dto.getPage(), dto.getPagesize(), toUserId);
        //得到推荐朋友集合
        List<RecommendUser> recommendUsers = (List<RecommendUser>) recommendation.getItems();
        if ( recommendUsers == null || recommendUsers.size() == 0){
            //判断能不能查到当前页的数据
            return recommendation;
        }
        //整个userId集合出来
        List<Long> userIds = recommendUsers.stream().map(RecommendUser::getUserId).collect(Collectors.toList());
        //拿这id们去查数据库userInfo表,还要带上一些指定条件
        UserInfo userInfo = new UserInfo();
        userInfo.setAge(dto.getAge());
        userInfo.setGender(dto.getGender());
        Map<Long,UserInfo> userInfos = userInfoApi.getByIds(userIds,userInfo);

        //如果一页中，没有一条是满足查询条件
        if (userInfos == null ){
            //递归调用自己，去查询下一页
            dto.setPage(dto.getPage() - 1);
            recommendation(dto);
        }
        //组装返回数据,组装为TodayBest对象
        List<TodayBest> list = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUsers) {
            //获取对应的userInfo
            UserInfo info = userInfos.get(recommendUser.getUserId());
            if (info != null){
                TodayBest todayBest = TodayBest.init(info, recommendUser);
                list.add(todayBest);
            }
        }
        recommendation.setItems(list);
        return recommendation;
    }

    /**
     * 查询今日佳人的信息
     * @param userId
     * @return
     */
    public TodayBest personalInfo(Long userId) {
        //查userInfo
        UserInfo userInfo = userInfoApi.getById(userId);
        //查recommendUser
        RecommendUser recommendUser = recommendUserApi.getOneTodayBest(userId,UserHolder.getUserId());

        //构造访客数据，并保存
        Visitors visitors = new Visitors();
        visitors.setDate(System.currentTimeMillis());
        visitors.setUserId(userId);
        visitors.setVisitorUserId(UserHolder.getUserId());
        visitors.setScore(recommendUser.getScore());
        visitors.setFrom("首页");
        visitors.setVisitDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        visitorsApi.save(visitors);
        return TodayBest.init(userInfo,recommendUser);
    }

    /**
     * 查询陌生人问题
     * @param userId
     * @return
     */
    public String strangerQuestions(Long userId) {
        Question question = questionApi.findByUserId(userId);
        //没有设置，给他整个默认的
        return question == null ? "who jb you?" : question.getTxt();
    }

    /**
     * 回复陌生人消息
     * @param userId
     * @param reply
     */
    public void strangerQuestion(long userId, String reply) {
        //当前发送人的id
        Long currentUserId = UserHolder.getUserId();
        UserInfo userInfo = userInfoApi.getById(currentUserId);
        //封装消息格式
        Map<String,Object> map = new HashMap<>();
        map.put("userId",currentUserId);
        map.put("huanXinId", Constants.HX_USER_PREFIX+currentUserId);
        map.put("nickname",userInfo.getNickname());
        map.put("strangerQuestion",strangerQuestions(userId));
        map.put("reply",reply);
        //转换为json
        String message = JSON.toJSONString(map);
        //发送
        huanXinTemplate.sendMsg(Constants.HX_USER_PREFIX + userId,message);
    }

    /**
     * 推荐列表查询
     * @return
     */
    public List<TodayBest> cards() {
        Long userId = UserHolder.getUserId();
        //查询推荐列表
        List<RecommendUser> recommendUserList = recommendUserApi.cards(userId,10);
        //判断是否存在此列表
        if (CollUtil.isEmpty(recommendUserList)){
            //没有，就给他指定一个默认列表
            recommendUserList = new ArrayList<>();
            String[] ids = recommendUsers.split(",");
            for (String id : ids) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Convert.toLong(id));
                recommendUser.setToUserId(UserHolder.getUserId());
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                recommendUserList.add(recommendUser);
            }
        }
        //提取列表中userIds
        List<Long> userIds = recommendUserList.stream().map(RecommendUser::getUserId).collect(Collectors.toList());

        //查询userInfo
        Map<Long, UserInfo> userInfos = userInfoApi.getByIds(userIds,null);
        List<TodayBest> list = new ArrayList<>();
        for (RecommendUser recommendUser : recommendUserList) {
            UserInfo userInfo = userInfos.get(recommendUser.getUserId());
            if (userInfo != null){
                TodayBest vo = TodayBest.init(userInfo, recommendUser);
                list.add(vo);
            }
        }

        return list;
    }

    /**
     * 喜欢
     */
    public void love(Long userLikeId) {
        //保存信息到表中
        Long userId = UserHolder.getUserId();
        Boolean save = userLikeApi.love(userId,userLikeId,true);
        if (!save){
            throw new BusinessException(ErrorResult.loveError());
        }
        //将redis中不喜欢数据给删了，在插入新的数据
        redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY + userId,userLikeId.toString());
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY + userId,userLikeId.toString());
        //判断两个人是不是双向喜欢,如果是直接加好友
        boolean flag = this.doubleLike(userLikeId,userId);
        if (flag){
            //直接加好友
            messagesService.contacts(userLikeId);
        }
    }

    /**
     * 判断是否位双向喜欢
     * @param userId
     * @param userLikeId
     * @return
     */
    private boolean doubleLike(Long userId, Long userLikeId) {
        return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(Constants.USER_LIKE_KEY + userId, userLikeId.toString()));
    }

    /**
     * 不喜欢
     */
    public void unLove(Long userLikeId) {
        //保存信息到表中
        Long userId = UserHolder.getUserId();
        Boolean save = userLikeApi.love(userId,userLikeId,false);
        if (!save){
            throw new BusinessException(ErrorResult.loveError());
        }
        //将redis中喜欢数据给删了，不喜欢的数据添加
        redisTemplate.opsForSet().remove(Constants.USER_LIKE_KEY + userId,userLikeId.toString());
        redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY + userId,userLikeId.toString());
        //判断两个是否双向喜欢，如果是直接删好友
        if (doubleLike(userLikeId,userId)){
            //删好友
            messagesService.deleteFriend(userLikeId);
        }
    }

    /**
     * 搜附近
     * @param gender
     * @param distance
     * @return
     */
    public List<NearUserVo> search(String gender, String distance) {
        //搜索附近的用户
        List<Long> userIds = userLocationApi.search(UserHolder.getUserId(),Double.parseDouble(distance));
        if (CollUtil.isEmpty(userIds)){
            return new ArrayList<>();
        }
        //去除自己的userId
        userIds.remove(UserHolder.getUserId());
        //根据userId查用户信息
        UserInfo condition = new UserInfo();
        condition.setGender(gender);
        Map<Long, UserInfo> userInfos = userInfoApi.getByIds(userIds, condition);
        //封装vo
        List<NearUserVo> list = new ArrayList<>();
        for (Long userId : userIds) {
            UserInfo userInfo = userInfos.get(userId);
            if (userInfo != null){
                NearUserVo vo = NearUserVo.init(userInfo);
                list.add(vo);
            }
        }
        return list;
    }


}
